#include "sqVirtualMachine.h"
#include "sqConfig.h"


#include "OpenVGPlugin.h"

  /* based on OpenVG 1.0.1 spec */

  VG_API_CALL VGErrorCode (*vgGetError) (void) = 0;
  VG_API_CALL void (*vgFlush) (void) = 0;
  VG_API_CALL void (*vgFinish) (void) = 0;

/* Getters and Setters */
  VG_API_CALL void (*vgSetf) (VGParamType type, VGfloat value) = 0;
  VG_API_CALL void (*vgSeti) (VGParamType type, VGint value) = 0;
  VG_API_CALL void (*vgSetfv) (VGParamType type, VGint count,
                         const VGfloat * values) = 0;
  VG_API_CALL void (*vgSetiv) (VGParamType type, VGint count,
                         const VGint * values) = 0;
  
  VG_API_CALL VGfloat (*vgGetf) (VGParamType type) = 0;
  VG_API_CALL VGint (*vgGeti) (VGParamType type) = 0;
  VG_API_CALL VGint (*vgGetVectorSize) (VGParamType type) = 0;
  VG_API_CALL void (*vgGetfv) (VGParamType type, VGint count, VGfloat * values) = 0;
  VG_API_CALL void (*vgGetiv) (VGParamType type, VGint count, VGint * values) = 0;

  VG_API_CALL void (*vgSetParameterf) (VGHandle object,
                                 VGint paramType,
                                 VGfloat value) = 0;
  VG_API_CALL void (*vgSetParameteri) (VGHandle object,
                                 VGint paramType,
                                 VGint value) = 0;
  VG_API_CALL void (*vgSetParameterfv) (VGHandle object,
                                  VGint paramType,
                                  VGint count, const VGfloat * values) = 0;
  VG_API_CALL void (*vgSetParameteriv) (VGHandle object,
                                  VGint paramType,
                                  VGint count, const VGint * values) = 0;

  VG_API_CALL VGfloat (*vgGetParameterf) (VGHandle object,
                                    VGint paramType) = 0;
  VG_API_CALL VGint (*vgGetParameteri) (VGHandle object,
                                  VGint paramType) = 0;
  VG_API_CALL VGint (*vgGetParameterVectorSize) (VGHandle object,
                                           VGint paramType) = 0;
  VG_API_CALL void (*vgGetParameterfv) (VGHandle object,
                                  VGint paramType,
                                  VGint count, VGfloat * values) = 0;
  VG_API_CALL void (*vgGetParameteriv) (VGHandle object,
                                  VGint paramType,
                                  VGint count, VGint * values) = 0;

/* Matrix Manipulation */
  VG_API_CALL void (*vgLoadIdentity) (void) = 0;
  VG_API_CALL void (*vgLoadMatrix) (const VGfloat * m) = 0;
  VG_API_CALL void (*vgGetMatrix) (VGfloat * m) = 0;
  VG_API_CALL void (*vgMultMatrix) (const VGfloat * m) = 0;
  VG_API_CALL void (*vgTranslate) (VGfloat tx, VGfloat ty) = 0;
  VG_API_CALL void (*vgScale) (VGfloat sx, VGfloat sy) = 0;
  VG_API_CALL void (*vgShear) (VGfloat shx, VGfloat shy) = 0;
  VG_API_CALL void (*vgRotate) (VGfloat angle) = 0;

/* Masking and Clearing */
  VG_API_CALL void (*vgMask) (VGImage mask, VGMaskOperation operation,
                        VGint x, VGint y, VGint width, VGint height) = 0;
  VG_API_CALL void (*vgClear) (VGint x, VGint y, VGint width, VGint height) = 0;

/* Paths */
  VG_API_CALL VGPath (*vgCreatePath) (VGint pathFormat,
                                VGPathDatatype datatype,
                                VGfloat scale, VGfloat bias,
                                VGint segmentCapacityHint,
                                VGint coordCapacityHint,
                                VGbitfield capabilities) = 0;
  VG_API_CALL void (*vgClearPath) (VGPath path, VGbitfield capabilities) = 0;
  VG_API_CALL void (*vgDestroyPath) (VGPath path) = 0;
  VG_API_CALL void (*vgRemovePathCapabilities) (VGPath path,
                                          VGbitfield capabilities) = 0;
  VG_API_CALL VGbitfield (*vgGetPathCapabilities) (VGPath path) = 0;
  VG_API_CALL void (*vgAppendPath) (VGPath dstPath, VGPath srcPath) = 0;
  VG_API_CALL void (*vgAppendPathData) (VGPath dstPath,
                                  VGint numSegments,
                                  const VGubyte * pathSegments,
                                  const void * pathData) = 0;
  VG_API_CALL void (*vgModifyPathCoords) (VGPath dstPath, VGint startIndex,
                                    VGint numSegments,
                                    const void * pathData) = 0;
  VG_API_CALL void (*vgTransformPath) (VGPath dstPath, VGPath srcPath) = 0;
  VG_API_CALL VGboolean (*vgInterpolatePath) (VGPath dstPath,
                                        VGPath startPath,
                                        VGPath endPath,
                                        VGfloat amount) = 0;
  VG_API_CALL VGfloat (*vgPathLength) (VGPath path,
                                 VGint startSegment, VGint numSegments) = 0;
  VG_API_CALL void (*vgPointAlongPath) (VGPath path,
                                  VGint startSegment, VGint numSegments,
                                  VGfloat distance,
                                  VGfloat * x, VGfloat * y,
                                  VGfloat * tangentX, VGfloat * tangentY) = 0;
  VG_API_CALL void (*vgPathBounds) (VGPath path,
                              VGfloat * minX, VGfloat * minY,
                              VGfloat * width, VGfloat * height) = 0;
  VG_API_CALL void (*vgPathTransformedBounds) (VGPath path,
                                         VGfloat * minX, VGfloat * minY,
                                         VGfloat * width, VGfloat * height) = 0;
  VG_API_CALL void (*vgDrawPath) (VGPath path, VGbitfield paintModes) = 0;

/* Paint */
  VG_API_CALL VGPaint (*vgCreatePaint) (void) = 0;
  VG_API_CALL void (*vgDestroyPaint) (VGPaint paint) = 0;
  VG_API_CALL void (*vgSetPaint) (VGPaint paint, VGbitfield paintModes) = 0;
  VG_API_CALL VGPaint (*vgGetPaint) (VGPaintMode paintMode) = 0;
  VG_API_CALL void (*vgSetColor) (VGPaint paint, VGuint rgba) = 0;
  VG_API_CALL VGuint (*vgGetColor) (VGPaint paint) = 0;
  VG_API_CALL void (*vgPaintPattern) (VGPaint paint, VGImage pattern) = 0;

/* Images */
  VG_API_CALL VGImage (*vgCreateImage) (VGImageFormat format,
                                  VGint width, VGint height,
                                  VGbitfield allowedQuality) = 0;
  VG_API_CALL void (*vgDestroyImage) (VGImage image) = 0;
  VG_API_CALL void (*vgClearImage) (VGImage image,
                              VGint x, VGint y, VGint width, VGint height) = 0;
  VG_API_CALL void (*vgImageSubData) (VGImage image,
                                const void * data, VGint dataStride,
                                VGImageFormat dataFormat,
                                VGint x, VGint y, VGint width, VGint height) = 0;
  VG_API_CALL void (*vgGetImageSubData) (VGImage image,
                                   void * data, VGint dataStride,
                                   VGImageFormat dataFormat,
                                   VGint x, VGint y,
                                   VGint width, VGint height) = 0;
  VG_API_CALL VGImage (*vgChildImage) (VGImage parent,
                                 VGint x, VGint y, VGint width, VGint height) = 0;
  VG_API_CALL VGImage (*vgGetParent) (VGImage image) = 0; 
  VG_API_CALL void (*vgCopyImage) (VGImage dst, VGint dx, VGint dy,
                             VGImage src, VGint sx, VGint sy,
                             VGint width, VGint height,
                             VGboolean dither) = 0;
  VG_API_CALL void (*vgDrawImage) (VGImage image) = 0;
  VG_API_CALL void (*vgSetPixels) (VGint dx, VGint dy,
                             VGImage src, VGint sx, VGint sy,
                             VGint width, VGint height) = 0;
  VG_API_CALL void (*vgWritePixels) (const void * data, VGint dataStride,
                               VGImageFormat dataFormat,
                               VGint dx, VGint dy,
                               VGint width, VGint height) = 0;
  VG_API_CALL void (*vgGetPixels) (VGImage dst, VGint dx, VGint dy,
                             VGint sx, VGint sy,
                             VGint width, VGint height) = 0;
  VG_API_CALL void (*vgReadPixels) (void * data, VGint dataStride,
                              VGImageFormat dataFormat,
                              VGint sx, VGint sy,
                              VGint width, VGint height) = 0;
  VG_API_CALL void (*vgCopyPixels) (VGint dx, VGint dy,
                              VGint sx, VGint sy,
                              VGint width, VGint height) = 0;

/* Image Filters */
  VG_API_CALL void (*vgColorMatrix) (VGImage dst, VGImage src,
                               const VGfloat * matrix) = 0;
  VG_API_CALL void (*vgConvolve) (VGImage dst, VGImage src,
                            VGint kernelWidth, VGint kernelHeight,
                            VGint shiftX, VGint shiftY,
                            const VGshort * kernel,
                            VGfloat scale,
                            VGfloat bias,
                            VGTilingMode tilingMode) = 0;
  VG_API_CALL void (*vgSeparableConvolve) (VGImage dst, VGImage src,
                                     VGint kernelWidth,
                                     VGint kernelHeight,
                                     VGint shiftX, VGint shiftY,
                                     const VGshort * kernelX,
                                     const VGshort * kernelY,
                                     VGfloat scale,
                                     VGfloat bias,
                                     VGTilingMode tilingMode) = 0;
  VG_API_CALL void (*vgGaussianBlur) (VGImage dst, VGImage src,
                                VGfloat stdDeviationX,
                                VGfloat stdDeviationY,
                                VGTilingMode tilingMode) = 0;
  VG_API_CALL void (*vgLookup) (VGImage dst, VGImage src,
                          const VGubyte * redLUT,
                          const VGubyte * greenLUT,
                          const VGubyte * blueLUT,
                          const VGubyte * alphaLUT,
                          VGboolean outputLinear,
                          VGboolean outputPremultiplied) = 0;
  VG_API_CALL void (*vgLookupSingle) (VGImage dst, VGImage src,
                                const VGuint * lookupTable,
                                VGImageChannel sourceChannel,
                                VGboolean outputLinear,
                                VGboolean outputPremultiplied) = 0;

/* Hardware Queries */
  VG_API_CALL VGHardwareQueryResult (*vgHardwareQuery) (VGHardwareQueryType key,
                                                  VGint setting) = 0;

/* Renderer and Extension Information */
  VG_API_CALL const VGubyte * (*vgGetString) (VGStringID name) = 0;


/******************************************* vgu.h *************************************/

  VGU_API_CALL VGUErrorCode(*vguLine)(VGPath path,
				  VGfloat x0, VGfloat y0,
				  VGfloat x1, VGfloat y1) = 0;

  VGU_API_CALL VGUErrorCode (*vguPolygon)(VGPath path,
				    const VGfloat * points, VGint count,
				    VGboolean closed) = 0;

  VGU_API_CALL VGUErrorCode (*vguRect)(VGPath path,
				 VGfloat x, VGfloat y,
				 VGfloat width, VGfloat height) = 0;

  VGU_API_CALL VGUErrorCode (*vguRoundRect)(VGPath path,
				      VGfloat x, VGfloat y,
				      VGfloat width, VGfloat height,
				      VGfloat arcWidth, VGfloat arcHeight) = 0;
  
  VGU_API_CALL VGUErrorCode (*vguEllipse)(VGPath path,
				    VGfloat cx, VGfloat cy,
				    VGfloat width, VGfloat height) = 0;

  VGU_API_CALL VGUErrorCode (*vguArc)(VGPath path,
				VGfloat x, VGfloat y,
				VGfloat width, VGfloat height,
				VGfloat startAngle, VGfloat angleExtent,
				VGUArcType arcType) = 0;

  VGU_API_CALL VGUErrorCode (*vguComputeWarpQuadToSquare)(VGfloat sx0, VGfloat sy0,
                                                    VGfloat sx1, VGfloat sy1,
                                                    VGfloat sx2, VGfloat sy2,
                                                    VGfloat sx3, VGfloat sy3,
                                                    VGfloat * matrix) = 0;

  VGU_API_CALL VGUErrorCode (*vguComputeWarpSquareToQuad)(VGfloat dx0, VGfloat dy0,
                                                    VGfloat dx1, VGfloat dy1,
                                                    VGfloat dx2, VGfloat dy2,
                                                    VGfloat dx3, VGfloat dy3,
                                                    VGfloat * matrix) = 0;

  VGU_API_CALL VGUErrorCode (*vguComputeWarpQuadToQuad)(VGfloat dx0, VGfloat dy0,
                                                  VGfloat dx1, VGfloat dy1,
                                                  VGfloat dx2, VGfloat dy2,
                                                  VGfloat dx3, VGfloat dy3,
						                          VGfloat sx0, VGfloat sy0,
                                                  VGfloat sx1, VGfloat sy1,
                                                  VGfloat sx2, VGfloat sy2,
                                                  VGfloat sx3, VGfloat sy3,
                                                  VGfloat * matrix) = 0;

/* Extensions - ShivaVG */

  VG_API_CALL VGboolean (*vgCreateContextSH) (VGint width, VGint height) = 0;
  VG_API_CALL void (*vgResizeSurfaceSH) (VGint width, VGint height) = 0;
  VG_API_CALL void (*vgDestroyContextSH) (void) = 0;


/****************************************************************************************************/
/* Squeak binding helpers																			*/


#define ALLFNNAMESDO(macro) \
 macro(vgGetError) \
 macro(vgFlush) \
 macro(vgFinish) \
 macro(vgSetf) \
 macro(vgSeti) \
 macro(vgSetfv) \
 macro(vgSetiv) \
 macro(vgGetf) \
 macro(vgGeti) \
 macro(vgGetVectorSize) \
 macro(vgGetfv) \
 macro(vgGetiv) \
 macro(vgSetParameterf) \
 macro(vgSetParameteri) \
 macro(vgSetParameterfv) \
 macro(vgSetParameteriv) \
 macro(vgGetParameterf) \
 macro(vgGetParameteri) \
 macro(vgGetParameterVectorSize) \
 macro(vgGetParameterfv) \
 macro(vgGetParameteriv) \
 macro(vgLoadIdentity) \
 macro(vgLoadMatrix) \
 macro(vgGetMatrix) \
 macro(vgMultMatrix) \
 macro(vgTranslate) \
 macro(vgScale) \
 macro(vgShear) \
 macro(vgRotate) \
 macro(vgMask) \
 macro(vgClear) \
 macro(vgCreatePath) \
 macro(vgClearPath) \
 macro(vgDestroyPath) \
 macro(vgRemovePathCapabilities) \
 macro(vgGetPathCapabilities) \
 macro(vgAppendPath) \
 macro(vgAppendPathData) \
 macro(vgModifyPathCoords) \
 macro(vgTransformPath) \
 macro(vgInterpolatePath) \
 macro(vgPathLength) \
 macro(vgPointAlongPath) \
 macro(vgPathBounds) \
 macro(vgPathTransformedBounds) \
 macro(vgDrawPath) \
 macro(vgCreatePaint) \
 macro(vgDestroyPaint) \
 macro(vgSetPaint) \
 macro(vgGetPaint) \
 macro(vgSetColor) \
 macro(vgGetColor) \
 macro(vgPaintPattern) \
 macro(vgCreateImage) \
 macro(vgDestroyImage) \
 macro(vgClearImage) \
 macro(vgImageSubData) \
 macro(vgGetImageSubData) \
 macro(vgChildImage) \
 macro(vgGetParent) \
 macro(vgCopyImage) \
 macro(vgDrawImage) \
 macro(vgSetPixels) \
 macro(vgWritePixels) \
 macro(vgGetPixels) \
 macro(vgReadPixels) \
 macro(vgCopyPixels) \
 macro(vgColorMatrix) \
 macro(vgConvolve) \
 macro(vgSeparableConvolve) \
 macro(vgGaussianBlur) \
 macro(vgLookup) \
 macro(vgLookupSingle) \
 macro(vgHardwareQuery) \
 macro(vgGetString) \
 macro(vguLine) \
 macro(vguPolygon) \
 macro(vguRect) \
 macro(vguRoundRect) \
 macro(vguEllipse) \
 macro(vguArc) \
 macro(vguComputeWarpQuadToSquare) \
 macro(vguComputeWarpSquareToQuad) \
 macro(vguComputeWarpQuadToQuad) \
 macro(vgCreateContextSH) \
 macro(vgResizeSurfaceSH) \
 macro(vgDestroyContextSH) \
 macro(vgInitContextAM) \
 macro(vgDestroyContextAM) \
 macro(vgResizeSurfaceAM) \
 macro(vgGetSurfaceWidthAM) \
 macro(vgGetSurfaceHeightAM) \
 macro(vgGetSurfaceFormatAM) \
 macro(vgGetSurfacePixelsAM) \
 macro(vgPostSwapBuffersAM)


#define VG_LOAD_FN(name) name = ioGetVGSymbolPtr(#name);

void ioInitializeVgFnPointers()
{
	ALLFNNAMESDO(VG_LOAD_FN);
}

#define VG_CLEAR_FN(name) name = 0;

void ioClearFunctionPointers()
{
	ALLFNNAMESDO(VG_CLEAR_FN);
}

void * ioGetVGSymbolPtrNameLength(char * symName, int nameLength)
{
	char * str = alloca(nameLength+1);

	if (!str) return 0;
	memcpy(str, symName, nameLength);
	str[nameLength] = 0;

	return ioGetVGSymbolPtr(str);
}
